package cloud.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Query;

import cloud.beans.Anime;
import cloud.beans.Staff;
import cloud.config.CacheController;

/**
 * Classe implémentant l'interface UtilisateurDao @see {@link AnimeDao}
 * @author Alexis JULIEN & R&eacute;mi OGNARD pour TERCA
 * @version 1.0
 */
public class StaffDao {
	
	/**
	 * L'objet permettant de faire le lien avec la table.
	 */
	private DatastoreService datastore;
	
	/**
	 * Emsemble des erreurs produites.
	 */
	private ArrayList<String> erreursDAO;
	
	public StaffDao() {
		
		this.datastore = DatastoreServiceFactory.getDatastoreService();
		erreursDAO = new ArrayList<String>();
	}
		
	
	/** Implémentation de la méthode définie dans l'interface UtilisateurDao 
	 * @see {@link AnimeDao#creer(Utilisateur)}
	*/
	public boolean creer( Staff staff ) throws DAOException {
		
		//create Entity type "Anime"
		Entity staffEntity = new Entity("Staff");
		
		//set Entity properties to Anime
		staffEntity.setProperty("anime_id", staff.getAnime_id());
		staffEntity.setProperty("person_id", staff.getPerson_id());
		staffEntity.setProperty("role", staff.getRole());
		
		//save Entity to the datastore
		datastore.put(staffEntity);
		//save Entity in MemCache
		CacheController.put("anime", staff);
		
		return true;
	}
	
	/* Implémentation de la méthode définie dans l'interface UtilisateurDao */
	public Staff trouver( long id ) {
	
		Staff staff = new Staff();
		
		//gets the Object in MemCache if it exists
    	if(CacheController.containsKey(id)) {
    		System.out.println("recupere dans le cache");
    		staff = (Staff) CacheController.get(id);
    	}
    	
    	//else gets the Object in Datastore 
    	else {
    		System.out.println("recupere dans le datastore");
			try {
				Key key = KeyFactory.createKey("Staff", id);
				Entity result = datastore.get(key);
				staff = map( result );

    	    	//save Entity to the MemCache
    	    	CacheController.put(result.getKey().getId(), staff);
			}
			 catch ( SQLException | EntityNotFoundException e ) {
				erreursDAO.add( e.getMessage() );
			}
    	}
		return staff;
	}
	
	/* Implémentation de la méthode définie dans l'interface UtilisateurDao */
	public List<Staff> lister( long id ) {
		
		List<Staff> staffList = new ArrayList<Staff>();
		Staff staff;
			
		try {
			Query query = new Query("Staff").setFilter(new Query.FilterPredicate("anime_id", Query.FilterOperator.EQUAL, id));
	    	List<Entity> results = datastore.prepare(query).asList(FetchOptions.Builder.withDefaults());  	
	    	
	    	for(Entity result : results){    		
	    		staff = map(result);
	    		//save Entity to the MemCache
	    		CacheController.put(result.getKey().getId(), staff);
	    		staffList.add(staff);
	    	}
		}
		 catch ( SQLException e ) {
				erreursDAO.add( e.getMessage() );
			}
	    	
	    return staffList;
	} 
	
	
	/* Implémentation de la méthode définie dans l'interface UtilisateurDao */
	public List<Staff> listerForPerson( long id ) {
		
		List<Staff> staffList = new ArrayList<Staff>();
		Staff staff;
			
		try {
			Query query = new Query("Staff").setFilter(new Query.FilterPredicate("person_id", Query.FilterOperator.EQUAL, id));
	    	List<Entity> results = datastore.prepare(query).asList(FetchOptions.Builder.withDefaults());  	
	    	
	    	for(Entity result : results){    		
	    		staff = map(result);
	    		//save Entity to the MemCache
	    		CacheController.put(result.getKey().getId(), staff);
	    		staffList.add(staff);
	    	}
		}
		 catch ( SQLException e ) {
				erreursDAO.add( e.getMessage() );
			}
	    	
	    return staffList;
	} 
	
	/**
	* Simple méthode utilitaire permettant de faire la correspondance (le
	* mapping) entre une ligne issue de la table des utilisateurs (un
	* ResultSet) et un bean Utilisateur.
	*/
	private static Staff map( Entity result ) throws SQLException {
		
		Staff staff = new Staff();
		
		staff.setAnime_id( (long) result.getProperty( "anime_id" ) );
		staff.setPerson_id( (long) result.getProperty( "person_id" ) );
		staff.setRole( (String) result.getProperty( "role" ) );

		return staff;
	}
}
